package org.ediba.siri.core.request.data;

import java.util.Collection;
import java.util.Map;

import org.ediba.siri.core.Filter;
import org.ediba.siri.core.common.data.HibernateDomainDao;
import org.ediba.siri.core.request.domain.Request;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

public class HibernateRequestDao extends HibernateDomainDao<Request, Integer> implements RequestDao {

	public HibernateRequestDao() {super(Request.class);}

	@Override
	protected DetachedCriteria buildCriteria(Collection<Map<Filter, Object>> filters) {
		DetachedCriteria detachedCriteria = this.buildCriteria();
		
		Disjunction or = Restrictions.disjunction();
		Conjunction and;

		for (Map<Filter, Object> map : filters) {
			and = Restrictions.conjunction();
			for (Map.Entry<Filter,Object> entry: map.entrySet())
				switch (entry.getKey()) {
				case ID: 		and.add(Restrictions.idEq((Integer)entry.getValue()));
				break;
				case USER: and.add(Restrictions.eq(Filter.USER.getPropertyId(), (Integer)entry.getValue()));
				break;
				case NUMBER: 
					if (entry.getValue()!=null)
						and.add(Restrictions.eq(Filter.NUMBER.getProperty(), (Integer)entry.getValue()));
					else and.add(Restrictions.isNull(Filter.NUMBER.getProperty()));
				break;
				case REQUEST_TYPE: and.add(Restrictions.eq(Filter.REQUEST_TYPE.getProperty(), (Boolean)entry.getValue()));
				break;
				case PENDING: and.add(Restrictions.eq(Filter.PENDING.getProperty(), (Boolean)entry.getValue()));
				break;
				case NUMBERSTR:
					and.add(Restrictions.ilike(Filter.NUMBERSTR.getProperty(), (String)entry.getValue(),MatchMode.START));
				break;
				case PUBLICATION: 
					if ((Integer)entry.getValue()==0)
						and.add(Restrictions.isNull(Filter.PUBLICATION.getPropertyId()));
					else and.add(Restrictions.eq(Filter.PUBLICATION.getPropertyId(), entry.getValue()));
				break;
				}
			or.add(and);
		}
		
		detachedCriteria.add(or);
		//detachedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		return detachedCriteria;
	}
	
	@Override
	protected DetachedCriteria buildCriteria(Map<Filter, Collection<Object>> filters) {
		DetachedCriteria detachedCriteria = this.buildCriteria();
		Disjunction or;
		Conjunction and = Restrictions.conjunction();
		
		for (Map.Entry<Filter,Collection<Object>> filter : filters.entrySet()){
			or = Restrictions.disjunction();
			for (Object value : filter.getValue())
				switch (filter.getKey()) {
				case ID: or.add(Restrictions.idEq((Integer)value));
				break;
				case USER: or.add(Restrictions.eq(Filter.USER.getPropertyId(), (Integer)value));
				break;
				case REQUEST_TYPE: or.add(Restrictions.eq(Filter.REQUEST_TYPE.getProperty(), (Boolean)value));
				break;
				case PENDING: or.add(Restrictions.eq(Filter.PENDING.getProperty(), (Boolean)value));
				break;
				case NUMBER:
					if (value!=null&&(Integer)value!=0){
						or.add(Restrictions.eq(Filter.NUMBER.getProperty(), (Integer)value)); 	
					}else or.add(Restrictions.isNull(Filter.NUMBER.getProperty()));
				break;
				case NUMBERSTR:
					or.add(Restrictions.ilike(Filter.NUMBERSTR.getProperty(), (String)value,MatchMode.START));
				break;
				case PUBLICATION:
					if ((Integer)value==0)
						or.add(Restrictions.isNull(Filter.PUBLICATION.getPropertyId()));
					else or.add(Restrictions.eq(Filter.PUBLICATION.getPropertyId(), value));
				break;
				}
			and.add(or);
		}
		
		if (!(filters.containsKey(Filter.NUMBER)))
			and.add(Restrictions.isNotNull(Filter.NUMBER.getProperty()));
		
		detachedCriteria.add(and);
		//detachedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		return detachedCriteria;
	}
}
